home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
asmutil
/
asm_n_z.zip
/
VISITYPE.ASM
< prev
next >
Wrap
Assembly Source File
|
1987-01-28
|
15KB
|
316 lines
VECTORS SEGMENT AT 0H ;Set up segment to intercept Interrupts
ORG 9H*4 ;The keyboard Interrupt
KEYBOARD_INT LABEL WORD
ORG 1CH*4 ;Timer Interrupt
TIMER_VECTOR LABEL WORD
VECTORS ENDS
SCREEN SEGMENT AT 0B000H ;A dummy segment to use as the
SCREEN ENDS ;Extra Segment
ROM_BIOS_DATA SEGMENT AT 40H ;BIOS statuses held here, also keyboard buffer
ORG 1AH
HEAD DW ? ;Unread chars go from Head to Tail
TAIL DW ?
BUFFER DW 16 DUP (?) ;The buffer itself
BUFFER_END LABEL WORD
ROM_BIOS_DATA ENDS
CODE_SEG SEGMENT
ASSUME CS:CODE_SEG
ORG 100H ;ORG = 100H to make this into a .COM file
FIRST: JMP LOAD_BUFFER ;First time through
COPY_RIGHT DB 'Copyright 1986 Ziff-Davis Publishing Co.'
BUFF DW 0
BUFF2 DW 159 DUP(0)
PAD_OFFSET DW 0 ;Chooses 1st 160 bytes or 2nd
SCREEN_SEG_OFFSET DW 0 ;0 for mono, 8000H for graphics
IO_CHAR DW 1 ;Holds addr of Put or Get_Char
OLD_HEAD DW 1 ;To check for typeahead.
DISPLAY_ON DB 0 ;0 --> Off.
STATUS_PORT DW 0 ;Video controller status port
NEAR_ATTRIB_FLAG DB 0 ;Used in Put_Char
OLD_KEYBOARD_INT_LABEL LABEL DWORD
OLD_KEYBOARD_INT DW 0 ;Location of old kbd interrupt
DW 0
ROM_TIMER_LABEL LABEL DWORD
ROM_TIMER DW 0 ;The Timer interrupt's address
DW 0
BUFSTUFF PROC NEAR ;The keyboard interrupt will now come here.
ASSUME CS:CODE_SEG
PUSH AX ;Save the used registers for good form
PUSH BX
PUSH CX
PUSH DX
PUSH DI
PUSH SI
PUSH DS
PUSH ES
PUSHF ;First, call old keyboard interrupt
CALL OLD_KEYBOARD_INT_LABEL
ASSUME DS:ROM_BIOS_DATA ;Examine the char just put in
MOV BX,ROM_BIOS_DATA
MOV DS,BX
MOV BX,TAIL ;Point to current tail
CMP BX,HEAD ;If at head, kbd int has deleted char
JNE CONT
JMP OUT ;So leave
CONT: MOV DX,TAIL ;Read a char -- head advances.
SUB DX,2 ;Point to just read in character
CMP DX,OFFSET BUFFER ;Did we undershoot buffer?
JAE NOWRAP ;Nope
MOV DX,OFFSET BUFFER_END ;Yes -- move to buffer top
SUB DX,2
NOWRAP: MOV BX,DX
MOV CX,[BX] ;Get key in CX
CMP CX,BUFF ;Is it where we were before?
JNE T10
MOV BX,HEAD ;Has the head moved?
CMP BX,OLD_HEAD
JE T11 ;If yes, we have moved.
T10: CMP BUFF2,0
JNE REMOVE ;If there's something in BUFF2,
T11: CMP DX,HEAD ; remove char in kbd buffer.
JNE REMOVE
JMP OUT ;Do nothing this pass.
;More than one char in buffer -- Remove One!
REMOVE: MOV BX,DX
MOV TAIL,DX ;Remove character by adjusting tail.
MOV DX,[BX] ;Store character in buffer.
MOV CX,80
MOV BX,0 ;Find end of visitype buffer.
CHECK: CMP BUFF2[BX],0
JE BUFEND
ADD BX,2
LOOP CHECK
CMP DX,0E08H ;Was this key a rubout?
JNE OUT ;No, and buffer filled -- leave.
MOV BX,158 ;Yes, buff full but rubout last char.
MOV WORD PTR BUFF[BX],0
MOV BX,HEAD
MOV OLD_HEAD,BX ;Store this for next time.
MOV DX,[BX] ;Always load BUFF.
MOV BUFF,DX
JMP OUT ;Can't hold more than 80!
BUFEND: CMP DX,0E08H ;Rubout (and buffer not full)?
JNE NODEL ;No, don't del.
DEL: SUB BX,2 ;Yes, delete last key.
CMP BX,0FFFEH ;Gone too far?
JL OUT
JNE PADDEL
MOV CX,TAIL ;Del the one char in kdb buffer
MOV HEAD,CX ; by making tail = head.
MOV BUFF,0
JMP SHORT CHKDIS
PADDEL: MOV DX,0 ;DX --> 0 if we are deleting.
NODEL: MOV BUFF2[BX],DX ;Load key in Visitype buffer.
MOV BX,HEAD
MOV OLD_HEAD,BX ;And store the old head to check later.
MOV DX,[BX] ;Always reload BUFF.
MOV BUFF,DX
CHKDIS: CMP DISPLAY_ON,0 ;Are we on?
JNE FLASH ;Yes, call DISPLAY
MOV DISPLAY_ON,0FFH ;Store what's on the screen first.
MOV PAD_OFFSET,160
LEA AX,GET_CHAR ;Make IO use Get-Char so it does.
MOV IO_CHAR,AX
CALL IO ;Get top line from screen.
FLASH: CALL DISPLAY ;Display VISITYPE's top line.
OUT: POP ES ;Having done Pushes, here are the Pops
POP DS
POP SI
POP DI
POP DX
POP CX
POP BX
POP AX
IRET ;An interrupt needs an IRET
BUFSTUFF ENDP
DISPLAY PROC NEAR ;Puts the whole pad on the screen
PUSH AX
MOV NEAR_ATTRIB_FLAG,0
MOV PAD_OFFSET,0 ;Use 1st bytes of pad memory
LEA AX,PUT_CHAR ;Make IO use Put-Char so it does
MOV IO_CHAR,AX
CALL IO ;Put result on screen
POP AX
RET ;Leave
DISPLAY ENDP
GET_CHAR PROC NEAR ;Gets a char from screen and advances position
ASSUME ES:SCREEN,DS:ROM_BIOS_DATA
PUSH DX
MOV SI,2 ;Loop twice, once for char, once for attribute
MOV DX,STATUS_PORT ;Get ready to read video controller status
G_WAIT_LOW: ;Start waiting for a new horizontal scan -
IN AL,DX ;Make sure the video controller scan status
TEST AL,1 ;is low
JNZ G_WAIT_LOW
G_WAIT_HIGH: ;After port has gone low, it must go high
IN AL,DX ;before it is safe to read directly from
TEST AL,1 ;the screen buffer in memory
JZ G_WAIT_HIGH
MOV AX,ES:[DI] ;Do the move from the screen, one byte at a time
INC DI ;Move to next screen location
DEC SI ;Decrement loop counter
CMP SI,0 ;Are we done?
JE LEAVE ;Yes
MOV BUFF[BX],AX ;No -- put char we got into BUFF.
JMP G_WAIT_LOW ;Do it again
LEAVE: ADD BX,2
POP DX
RET
GET_CHAR ENDP
PUT_CHAR PROC NEAR ;Puts one char on screen and advances position
PUSH DX
CLI
MOV AH,BYTE PTR BUFF[BX]
MOV SI,2 ;Loop twice, once for char, once for attribute
MOV DX,STATUS_PORT ;Get ready to